﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using AgnisEbmtTranslator;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace TestApplication
{
    // delegates used to call MainForm functions from worker thread
    public delegate void DelegateRefreshStatus(Object[] objs);
    public delegate void DelegateThreadFinished(Object[] objs);

    public partial class FormTest : Form
    {
       
        // Translator Thread declaration
        Thread myTranslatorThread;

        // events used to stop worker thread
        ManualResetEvent m_EventStopThread;
        ManualResetEvent m_EventThreadStopped;

        // Delegate instances used to call user interface functions 
        // from worker thread:
        public DelegateRefreshStatus  m_DelegateRefreshStatus;
        public DelegateThreadFinished m_DelegateThreadFinished;

        private int nTransplants=1;

        private String currentEbmtDbConnectionString;
        private String currentMappingInfoConnectionString;
        private String currentAgnisStagingConnectionString;

        AgnisDAL.ServiceAgnis.FormRevision myGeneratedFormRevision;

        AgnisDAL.ServiceAgnis.FormRevision myFake2400FormRevision;

        public void SetCurrentEbmtDbConnectionString (String cString)
        {
            currentEbmtDbConnectionString = cString;
        }

        public void SetCurrentMappingInfoConnectionString(String cString)
        {
            currentMappingInfoConnectionString = cString;
        }

        public void SetCurrentAgnisStagingConnectionString(String cString)
        {
            currentAgnisStagingConnectionString = cString;
        }

        public FormTest()
        {
            InitializeComponent();

            // initialize delegates
            m_DelegateRefreshStatus = new DelegateRefreshStatus(this.RefreshStatus);
            m_DelegateThreadFinished = new DelegateThreadFinished(this.ThreadFinished);

            // initialize events
            m_EventStopThread = new ManualResetEvent(false);
            m_EventThreadStopped = new ManualResetEvent(false);


        }

        DateTime t1;
        TimeSpan  t2;
        // Called from worker thread using delegate and Control.Invoke
        public void RefreshStatus(Object[] obj)
        {
            if ((bool)obj[3] == true)
            {
                txtProgress.Text = txtProgress.Text + "Processing ID:" + obj[0].ToString() + ", IDAA:" + obj[1].ToString() + ", date of transplant:" + obj[2].ToString()+ "\r\n";
                t1 = DateTime.Now;
                progressBar1.PerformStep();
            }
            else 
            {
                t2 = DateTime.Now -t1;
                txtProgress.Text = txtProgress.Text + "Process finished. Process executing time:\r\n" 
                    + t2.TotalSeconds + " seconds. \r\n";
            }
            txtProgress.SelectionStart = txtProgress.Text.Length - 1;
            txtProgress.ScrollToCaret();
        }

        // Called from worker thread using delegate and Control.Invoke
        public void ThreadFinished(Object[] objs)
        {
            btnSubmissionTest.Enabled = true;
            myGeneratedFormRevision = (AgnisDAL.ServiceAgnis.FormRevision)objs[0];
            myFake2400FormRevision = (AgnisDAL.ServiceAgnis.FormRevision)objs[1];
            
            this.btnEbmtAgnisTranslation.Enabled = true;
            chkSendToDataBase.Enabled = true;
            MessageBox.Show ("Done.");
        }

   
        private void FormTranslationTest_Load(object sender, EventArgs e)
        {

            SqlConnection myTestConnection = new SqlConnection(currentEbmtDbConnectionString);
            this.transplantsListTableAdapter.SetConnection(myTestConnection);
            this.transplantsListTableAdapter.Fill(this.ebmtDataSet.TransplantsList);
            progressBar1.Maximum = nTransplants;
            progressBar1.Step = 1;
        }


        
        private void btnEbmtAgnisTranslation_Click(object sender, EventArgs e)
        {
            int formNumber ;
            switch (cbFormNumber.SelectedIndex)
            {
                case 0:
                    formNumber = 2804;
                    break;
                case 1:
                    formNumber = 2400;
                    break;
                case 2:
                    formNumber = 2450;
                    break;
                default:
                    formNumber = 2900;
                    break;

            }
            
            btnSubmissionTest.Enabled = false;
            btnEbmtAgnisTranslation.Enabled = false;
            chkSendToDataBase.Enabled = false;
            // Instantating the translation thread, we specify into the ThreadStart delegate
            // the name of the method that will be executed when we call Start() thread.
            MyTranslatorThreadHandle tHandle = new MyTranslatorThreadHandle(this.bsTransplantsList , this, m_EventStopThread, m_EventThreadStopped);
            tHandle.AgnisPaperFormNumber = formNumber;
            tHandle.SetCurrentEbmtDbConnectionString(currentEbmtDbConnectionString);
            tHandle.SetCurrentMappingInfoConnectionString(currentMappingInfoConnectionString);
            tHandle.SetCurrentAgnisStagingConnectionString(currentAgnisStagingConnectionString);
            tHandle.StoreToDataBase = this.chkSendToDataBase.Checked;
            
            tHandle.NumberOfTransplantsToProcess = nTransplants;
            if (nTransplants == 1) tHandle.SelectedIndex = this.bsTransplantsList.IndexOf(this.bsTransplantsList.Current);
            progressBar1.Maximum = nTransplants;
            myTranslatorThread = new Thread(new ThreadStart(tHandle.ExecuteTranslationProcess));

            myTranslatorThread.Start();

        }

        // Stop worker thread if it is running.
        // Called when user presses Stop button or form is closed.
        private void StopTranslatorThread()
        {
            if (myTranslatorThread != null && myTranslatorThread.IsAlive)  // thread is active
            {
                // set event "Stop"
                m_EventStopThread.Set();

                // wait when thread  will stop or finish
                while (myTranslatorThread.IsAlive)
                {
                    // We cannot use here infinite wait because our thread
                    // makes syncronous calls to main form, this will cause deadlock.
                    // Instead of this we wait for event some appropriate time
                    // (and by the way give time to worker thread) and
                    // process events. These events may contain Invoke calls.
                    if (WaitHandle.WaitAll(
                        (new ManualResetEvent[] { m_EventThreadStopped }),
                        100,
                        true))
                    {
                        break;
                    }

                    Application.DoEvents();
                }
            }
        }

        private void FormTranslationTest_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopTranslatorThread();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBox1.SelectedIndex > -1)
            {
                if (!int.TryParse(comboBox1.SelectedItem.ToString(), out nTransplants))
                {                    
                    switch (comboBox1.SelectedItem.ToString())
                    {
                        case "ALL": nTransplants = bsTransplantsList.Count;
                            break;
                        case "SEL": nTransplants = aA_DataGridView.SelectedCells.Count;
                            break;
                        default: break;
                    }
                }
                else
                {
                    //nTransplants = 1;
                    nTransplants = Convert.ToInt32(comboBox1.SelectedItem.ToString());
                }
            }
            else 
            {
                nTransplants = 1;
            }
            
          
        }

        private void btnSubmissionTest_Click(object sender, EventArgs e)
        {
            AgnisDAL.ServiceAgnis.FormRevision resultingFake2400FRev = AgnisDAL.cAgnisDAL.SendFormRevision(myGeneratedFormRevision);
            AgnisDAL.ServiceAgnis.FormRevision resultingFRev = AgnisDAL.cAgnisDAL.SendFormRevision(myGeneratedFormRevision);
            string xmlOutput = SerializeObjectToXmlString(resultingFake2400FRev);
            string xmlOutput2 = SerializeObjectToXmlString(resultingFRev);

            string fileName = TestApplication.Properties.Settings.Default.OutputXmlDir + "form_2400_fake_PublicID_XXXX_response.xml";
            string fileName2 = TestApplication.Properties.Settings.Default.OutputXmlDir + "form_2450_PublicID_XXXX_response.xml";
            fileName = fileName.Replace("_XXXX_", "_" + resultingFake2400FRev.formId + "_");
            fileName2 = fileName2.Replace("_XXXX_", "_" + resultingFRev.formId + "_");
            
            StreamWriter sWriter = new StreamWriter(fileName, false);
            StreamWriter sWriter2 = new StreamWriter(fileName2, false);
            sWriter.Write(xmlOutput);
            sWriter2.Write(xmlOutput2);
            sWriter.Close();
            sWriter2.Close();
        }
        #region XML related methods
        public static string SerializeObjectToXmlString(object obj)
        {
            XmlTextWriter writer = new XmlTextWriter(new MemoryStream(), Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            serializer.Serialize(writer, obj);
            MemoryStream stream = (MemoryStream)writer.BaseStream;
            string xmlString = UTF8ByteArrayToString(stream.ToArray());
            return xmlString;
        }

        public static string UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetString(characters);
        }

        private AgnisDAL.ServiceAgnis.FormRevision LoadFormRevisionObjectFromXMLDoc(String xmlFileName)
        {
            //Read a xml file corresponding to form.
            System.IO.FileStream fs =
             System.IO.File.OpenRead(xmlFileName);
            System.IO.StreamReader sr = new System.IO.StreamReader(fs);
            string data = sr.ReadToEnd();

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(data);
            //Serialize the file data using the FormRevision data type.
            XmlSerializer s = new XmlSerializer(typeof(AgnisDAL.ServiceAgnis.FormRevision));
            string xmlString = doc.OuterXml.ToString();
            byte[] buffer = ASCIIEncoding.UTF8.GetBytes(xmlString);
            MemoryStream ms = new MemoryStream(buffer);
            XmlReader reader = new XmlTextReader(ms);
            Exception caught = null;

            try
            {
                object o = s.Deserialize(reader);
                AgnisDAL.ServiceAgnis.FormRevision fInput = (AgnisDAL.ServiceAgnis.FormRevision)o;
                return fInput;
            }
            catch (Exception ex)
            {
                caught = ex;
            }
            finally
            {
                reader.Close();
            }
            return null;
        }

        #endregion

        private void btnSendXMLFile_Click(object sender, EventArgs e)
        {
           AgnisDAL.ServiceAgnis.FormRevision myFormRev;
           if (this.txtFileName.Text != "")
           {
               myFormRev = LoadFormRevisionObjectFromXMLDoc(this.txtFileName.Text);
               AgnisDAL.ServiceAgnis.FormRevision myFormRevAnswer = AgnisDAL.cAgnisDAL.SendFormRevision(myFormRev);
               string xmlOutput = SerializeObjectToXmlString(myFormRevAnswer);

               string fileName = TestApplication.Properties.Settings.Default.OutputXmlDir + @"\outputResponseXmlSentFile.xml";

               StreamWriter sWriter = new StreamWriter(fileName, false);
               sWriter.Write(xmlOutput);
               sWriter.Close();
               MessageBox.Show("FormRevision sent.");
           }
           
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                this.txtFileName.Text = this.openFileDialog1.FileName;
            }
            //this.openFileDialog1.Dispose();
        }

        private void btnForm2_Click(object sender, EventArgs e)
        {
            //FormTest2 oNextForm = new FormTest2(currentEbmtDbConnectionString,currentMappingInfoConnectionString,currentAgnisStagingConnectionString);
            //oNextForm.Show();
            this.Dispose();
            
        }

        private void btnSettings_Click(object sender, EventArgs e)
        {
            this.Close();
            FormContainer myContainer = new FormContainer();

            myContainer.OpenSettingsForm();
         
        }
    }
}
